/*
 * copyright (c) 2009 Alexandr [Sn@ble] Surnin
 *
 * This file is part of FrameSeeker.
 *
 * FrameSeeker is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * FrameSeeker is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You can read the full version of GNU LGPL in
 * http://www.gnu.org/copyleft/lesser.html
 */


#include "FSMVsContext.h"


FSMVsContext::FSMVsContext(int16_t (*m_val[2])[2], int _w, int _h, int _mSSL2, int _fType) {

    mvData = m_val;
    imgWidth = _w;
    imgHeight = _h;
    mvSampleLog2 = 4 - _mSSL2;
    frameType = _fType;
}

void FSMVsContext::extractMVs() {

    qDebug() << "extractMV(): before frameType";

    FSMotionVector *mv;

    // If current frame is not "I"-frame
    if (frameType != FS_FRAME_TYPE_I) {

        int shift = 1;

        // Horizontal count of macroblocks
        int mbWidth = (imgWidth + 15) >> 4; // devide by 16

        // Vertical count of macroblocks
        int mbHeight = (imgHeight + 15) >> 4; // devide by 16

        // Line offset (or something else?!)
        int mvStride = (mbWidth << mvSampleLog2) + 1;


        int mbX; // macro block "X" coordinate
        int mbY; // macro block "Y" coordinate
        int mvX; // motion vector "X" coordinate
        int mvY; // motion vector "Y" coordinate
        int xy; // (x + y * mvStride) << mvSampleLog2, if MB is 16X16
        int direction; // Direction of motion vector
        for (int x = 0; x < mbWidth; x++) {
            for (int y = 0; y < mbHeight; y++) {
                //int mbType = frameYUV->mb_type[x + y * mvStride];
                // direction == 0 for MBs "P"-for and "B"-for in "P" and "B" frames
                // direction == 1 for "B"-back MBs in "B" frames
                direction = 0;

                // Thats ONLY FOR 16X16 MBs!!!
                mbX = x * 16 + 8;
                mbY = y * 16 + 8;
                xy = (x + y * mvStride) << mvSampleLog2;
                qDebug() << "extractMV(): before mvX = ... ";
                mvX = mvData[direction][xy][0] >> shift;
                mvY = mvData[direction][xy][1] >> shift;
                qDebug() << "extractMV(): before new FSMotionVector()...";
                mv = new FSMotionVector(mbX, mbY, mvX, mvY);
                MVs << *mv;
                delete mv;
            }
        }


    } else {
        mv = new FSMotionVector(0, 0, 0, 0);
        MVs << *mv;
        delete mv;
    }
}


QList<FSMotionVector> FSMVsContext::getMVs() {

    qDebug() << "before isEmpty()";
    if (MVs.isEmpty()) {
        qDebug() << "before extractMVs()...";
        extractMVs();
    }

    return MVs;
}


void FSMVsContext::saveToDisk(QString &postfix) {

}

FSMVsContext::~FSMVsContext() {

        MVs.clear();

}


FSMVsContext::FSMVsContext(const FSMVsContext &orig) {

    imgWidth = orig.getImgWidth();
    imgHeight = orig.getImgHeight();
    frameType = orig.getFrameType();
    mvData = orig.mvData;
    mvSampleLog2 = orig.getMVSampleLog2();

}


FSMVsContext& FSMVsContext::operator=(const FSMVsContext &right) {

    FSMVsContext *result = new FSMVsContext(right.mvData,
                                            right.getImgWidth(),
                                            right.getImgHeight(),
                                            right.getMVSampleLog2(),
                                            right.getFrameType());
    return *result;
}


quint64 FSMVsContext::getImgWidth() const {

    return imgWidth;
}


quint64 FSMVsContext::getImgHeight() const {

    return imgHeight;
}

int FSMVsContext::getMVSampleLog2() const {

    return mvSampleLog2;
}

int FSMVsContext::getFrameType() const {

    return frameType;
}
